﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PlanningGIS.Framework;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.esriSystem;
using System.Runtime.InteropServices;
using PlanningGIS.Util.Log;

namespace PlanningGIS.DataConvert.model
{
   
    public class DataExcavate : Operator2Ex
    {
        private List<IFeatureClass> pFeatClses;          //目标要素类
        private IPolygon pPolygonExcavate;               //挖除范围

        private int totalCount;                       //需要处理的总数
        private int errorCount;                       //处理的错误记录个数
        private int rightCount;                       //处理的成功记录个数

        //private int callbacknum = 0;                       //游标遍历到多少个回收一次
        private bool progress = false;              //是否计算进度条

        #region DataExcavate members

        /// <summary>
        /// 目标要素类
        /// </summary>
        public List<IFeatureClass> FeatClses
        {
            get { return pFeatClses; }
            set { pFeatClses = value; }
        }

        /// <summary>
        /// 要素总数，方便进度条显示
        /// </summary>
        public int TotalCount
        {
            get { return totalCount; }
            set { totalCount = value; }
        }

        /// <summary>
        /// 出错总数
        /// </summary>
        public int ErrorCount
        {
            get { return errorCount; }
        }

        /// <summary>
        /// 成功总数
        /// </summary>
        public int RightCount
        {
            get { return rightCount; }
        }

        ///// <summary>
        ///// 游标遍历多少个回收一次，如果为零则中途不回收
        ///// </summary>
        //public int CallbacknNum
        //{
        //    set { callbacknum = value; }
        //}

        /// <summary>
        /// 是否计算进度条
        /// </summary>
        public bool Progress
        {
            set { progress = value; }
        }

        /// <summary>
        ///设置挖除范围
        /// </summary>
        public IPolygon ExcavatePolygon
        {
            set { pPolygonExcavate = value; }
        }

        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        public DataExcavate()
        {
            totalCount = 0;
            errorCount = 0;
            rightCount = 0;
        }

        /// <summary>
        /// 数据挖除
        /// </summary>
        /// <returns></returns>
        public override bool Operate()
        {
            stopAnyway = false;
            int count = 1;
            errorCount = 0;
            rightCount = 0;

            bool hasErr = false;

            ISpatialFilter pSpatialFilter;

            bool result;

            if (pFeatClses == null || pFeatClses.Count == 0)
            {
               LogHelper.WriteErrLog("请设置需要被挖除的数据源！");
                return false;
            }
            if (pPolygonExcavate == null || pPolygonExcavate.IsEmpty)
            {
               LogHelper.WriteErrLog("请正确设置挖除范围！");
                return false;
            }

            setProcessBarMax(pFeatClses.Count);
            foreach (IFeatureClass pFeatCls in pFeatClses)
            {
                if (stopAnyway) return false;

                int totalDelete = 0;
                int errorDelete = 0;
                int errtotalDelete = 0;

                int totalExcavate = 0;
                int errorExcavate = 0;
                int errtotalExcavate = 0;

                setProcessBarCurrent(count++);
                LogHelper.WriteLog("开始对[" + pFeatCls.AliasName + "]数据进行挖除...");

                IPolygon pPolygon = (pPolygonExcavate as IClone).Clone() as IPolygon;
                ITopologicalOperator2 pTop = pPolygon as ITopologicalOperator2;
                pTop.IsKnownSimple_2 = false;
                pTop.Simplify();
                pPolygon.SpatialReference = (pFeatCls as IGeoDataset).SpatialReference;

                pSpatialFilter = new SpatialFilterClass();
                pSpatialFilter.Geometry = pPolygon;
                pSpatialFilter.GeometryField = pFeatCls.ShapeFieldName;

                //如果是注记类要素或者是点状要素，则无需裁切，只要跟挖除范围相交的部分直接删除
                if (pFeatCls.FeatureType == esriFeatureType.esriFTAnnotation ||
                    (pFeatCls.FeatureType == esriFeatureType.esriFTSimple && pFeatCls.ShapeType == esriGeometryType.esriGeometryPoint))
                {
                    pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

                    result = DeleteFeauresRapidnessFlush(pFeatCls, pSpatialFilter,out totalDelete);
                    if (result)
                    {
                        totalCount += totalDelete;
                        LogHelper.WriteDoneLog("[" + pFeatCls.AliasName + "]数据挖除完毕。处理总数：" + totalDelete + "个；成功：" + totalDelete + "个；失败：0个。\n");
                    }
                    else
                    {
                        LogHelper.WriteLog("快速挖除遇到部分异常要素，开始对这些异常要素逐个遍历...");

                        result = DeleteFeauresOneByOne(pFeatCls, pSpatialFilter,out errorDelete ,out errtotalDelete);
                        if (result)
                        {
                            totalCount += totalDelete;
                            LogHelper.WriteDoneLog("[" + pFeatCls.AliasName + "]数据挖除完毕。处理总数：" + totalDelete + "个；成功：" + totalDelete + "个；失败：0个。\n");
                        }
                        else
                        {
                            if (errorDelete == -1)
                            {
                                hasErr = true;//如果error为-1，则无法计算成功多少，失败多少
                               LogHelper.WriteErrLog("[" + pFeatCls.AliasName + "]数据挖除完毕。但仍然有部分要素挖除失败！\n");
                            }
                            else
                            {
                                totalDelete = (totalDelete == 0 ? errtotalDelete : totalDelete);
                                totalCount += totalDelete;
                                errorCount += errorDelete;
                               LogHelper.WriteErrLog("[" + pFeatCls.AliasName + "]数据挖除完毕。处理总数：" + totalDelete + "个；成功：" + (totalDelete - errorDelete) + "个；失败：" + errorDelete + "个。\n");
                            }
                        }
                    }
                }
                //如果是线或者面状要素，则先将完全被包含的部分删除掉，再将相交的部分进行裁切
                else
                {
                    #region 删除完全被包含的数据
                    LogHelper.WriteLog("正在删除完全包含在挖除范围内的数据...");
                    pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;

                    result = DeleteFeauresRapidnessFlush(pFeatCls, pSpatialFilter,out totalDelete);
                    if (result)
                    {
                        totalCount += totalDelete;
                        LogHelper.WriteDoneLog("完全包含在挖除范围内的数据删除完毕。处理总数：" + totalDelete + "个；成功：" + totalDelete + "个；失败：0个。");
                    }
                    else
                    {
                        LogHelper.WriteLog("快速删除遇到部分异常要素，开始对这些异常要素逐个遍历...");

                        result = DeleteFeauresOneByOne(pFeatCls, pSpatialFilter,out errorDelete,out errtotalDelete);
                        if (result)
                        {
                            totalCount += totalDelete;
                            LogHelper.WriteDoneLog("完全包含在挖除范围内的数据删除完毕。处理总数：" + totalDelete + "个；成功：" + totalDelete + "个；失败：0个。");
                        }
                        else
                        {
                            if (errorDelete == -1)
                            {
                                hasErr = true;//如果error为-1，则无法计算成功多少，失败多少
                               LogHelper.WriteErrLog("完全包含在挖除范围内的数据删除完毕。但仍然有部分要素删除失败！");
                            }
                            else
                            {
                                totalDelete = (totalDelete == 0 ? errtotalDelete : totalDelete);
                                totalCount += totalDelete;
                                errorCount += errorDelete;
                               LogHelper.WriteErrLog("完全包含在挖除范围内的数据删除完毕。处理总数：" + totalDelete + "个；成功：" + (totalDelete - errorDelete) + "个；失败：" + errorDelete + "个。");
                            }
                        }
                    }
                    #endregion

                    #region 挖除部分相交的数据
                    LogHelper.WriteLog("正在挖除部分相交的数据...");

                    pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

                    //如果相交也用删除的方式，先快速选一遍，再把异常的逐个遍历，会有这样的问题：当出现异常时，前面已经切割好的要素因为在
                    //范围线边缘还是会相交，所以后面还是会选中，那么就会导致所有快速做的要素这里还是要逐个遍历一遍，就比较浪费时间了，因
                    //为范围线内部的要素已经在前面被删除掉，这里相交的要素就不会太多，所以直接逐个遍历效率更高
                    result = ExcavateFeaturesRapidnessFlush(pFeatCls, pSpatialFilter, pPolygon,out totalExcavate);
                    if (result)
                    {
                        totalCount += totalExcavate;
                        LogHelper.WriteDoneLog("部分相交的数据挖除完毕。处理总数：" + totalExcavate + "个；成功：" + totalExcavate + "个；失败：0个。");
                    }
                    else
                    {
                        LogHelper.WriteLog("快速挖除遇到部分异常要素，开始对这些异常要素逐个遍历...");

                        result = ExcavateFeaturesOneByOne(pFeatCls, pSpatialFilter, pPolygon, out errorExcavate, out errtotalExcavate);
                        if (result)
                        {
                            LogHelper.WriteDoneLog("部分相交的数据挖除完毕。处理总数：" + totalExcavate + "个；成功：" + totalExcavate + "个；失败：0个。");
                        }
                        else
                        {
                            if (errorExcavate == -1)
                            {
                                hasErr = true;//如果error为-1，则无法计算成功多少，失败多少
                               LogHelper.WriteErrLog("部分相交的数据挖除完毕。但仍然有部分要素挖除失败！");
                            }
                            else
                            {
                                totalExcavate = (totalExcavate == 0 ? errtotalExcavate : totalExcavate);
                                totalCount += totalExcavate;
                                errorCount += errorExcavate;
                               LogHelper.WriteErrLog("部分相交的数据挖除完毕。处理总数：" + totalExcavate + "个；成功：" + (totalExcavate - errorExcavate) + "个；失败：" + errorExcavate + "个。");
                            }
                        }
                    }
                    #endregion

                    int totalSub = totalDelete + totalExcavate;
                    int errorSub = errorDelete + errorExcavate;

                    if (result)
                    {
                        LogHelper.WriteDoneLog("[" + pFeatCls.AliasName + "]数据挖除完毕。处理总数：" + totalSub + "个；成功：" + totalSub + "个；失败：0个。\n");
                    }
                    else
                    {
                        if (errorExcavate == -1 || errorDelete == -1)
                        {
                           LogHelper.WriteErrLog("[" + pFeatCls.AliasName + "]数据挖除完毕。但仍然有部分要素挖除失败！\n");
                        }
                        else
                        {
                           LogHelper.WriteErrLog("[" + pFeatCls.AliasName + "]数据挖除完毕。处理总数：" + totalSub + "个；成功：" + (totalSub - errorSub) + "个；失败：" + errorSub + "个。\n");
                        }
                    }
                }

            }

            if (hasErr)
            {
               LogHelper.WriteErrLog("所有数据挖除完毕。但仍然有部分要素挖除失败！\n");
            }
            else
            {
                if (errorCount == 0)
                {
                    LogHelper.WriteDoneLog ("所有数据挖除完毕。处理总数：" + totalCount + "个；成功：" + totalCount + "个；失败：0个。\n");
                }
                else 
                {
                   LogHelper.WriteErrLog ("所有数据挖除完毕。处理总数：" + totalCount + "个；成功：" + (totalCount - errorCount) + "个；失败：" + errorCount + "个。\n");
                }
            }

            return true;
        }

        #region 完全包含在挖除范围的要素，直接删除

        /// <summary>
        /// 删除数据，一千条记录保存一次，用Flush的方式速度更快
        /// </summary>
        /// <param name="pFeatCls"></param>
        /// <param name="pSpatialFilter"></param>
        /// <param name="total">返回要删除的总数</param>
        /// <returns>如果删除过程中没有任何异常，则返回true；否则返回false</returns>
        private bool DeleteFeauresRapidnessFlush(IFeatureClass pFeatCls, ISpatialFilter pSpatialFilter,out int total)
        {
            bool result = true;
            total = 0;

            IWorkspaceEdit pWsEdit = (pFeatCls as IDataset).Workspace as IWorkspaceEdit;
            if (!pWsEdit.IsBeingEdited())
            {
                try
                {
                    pWsEdit.StartEditing(false);
                    pWsEdit.StartEditOperation();
                }
                catch (Exception ex)
                {
                   LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                    return false;
                }
            }

            int count = 1;
            int max = 0;

            if (progress)
            {
                LogHelper.WriteLog("正在计算包含在挖除范围内要素的总数，请耐心等待...");
                try
                {
                    //计算总数的时候加Try—Catch语句是因为，有时候数目过大，而硬件设备（主要指内存）满足不了需求时，会报内存的存储空间
                    //不足的异常，这里如果捕捉到的话，则直接跳过，以假进度条的方式来表示。下同
                    max = pFeatCls.FeatureCount(pSpatialFilter);
                    total = max;

                    if (max == 0) return true;
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog("数量过大，计算总数失败，只能以假进度条显示操作过程！"+ex.Message);
                }

            }

            setSubProcessBarMax(max);

            IFeatureCursor pFeatCursor = null;
            IFeature pFeature = null;

            try
            {
                pFeatCursor = pFeatCls.Update(pSpatialFilter, false);

                pFeature = pFeatCursor.NextFeature();

                while (pFeature != null)
                {
                    if (stopAnyway) return false;

                    setSubProcessBarCurrent(count++);

                    //如果删除或保存的时候出错，则后面需要逐条遍历把该要素找出来
                    try
                    {
                        pFeature.Delete();
                    }
                    catch
                    {
                        result = false;
                    }

                    Marshal.ReleaseComObject(pFeature);

                    if (count % 1000 == 0)
                    {
                        //如果保存失败，可能是这1000条记录中某一条出现异常，后面需要逐个遍历找出该要素
                        try
                        {
                            pFeatCursor.Flush();
                            pWsEdit.StopEditOperation();

                            //本来是想在这里先停止编辑，把这1000条记录保存一下，然后再重新打开编辑（下面以/*...*/注释掉的代码），以免使
                            //所有的编辑都在后面一次性保存，数据量大了不稳定，但是发现这样做的话，内存会疯长，到一定的程度就会报“读取或
                            //写入的内存发生异常。”的错误，但是把这一句屏蔽后，发现内存就不会疯长了，程序更加稳定。（但不知是何原因）
                            //pWsEdit.StopEditing(true);
                        }
                        catch
                        {
                            result = false;
                        }

                        //如果再次打开编辑操作失败，则直接返回false，并且操作的总数也不能按照该函数算了
                        try
                        {
                            pWsEdit.StartEditOperation();
                        }
                        catch(Exception ex)
                        { 
                            total = 0;
                           LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                            return false;
                        }

                        /*===========================================================================================================
                        //再次打开编辑
                        if (!pWsEdit.IsBeingEdited())
                        {
                            try
                            {
                                pWsEdit.StartEditing(false);
                                pWsEdit.StartEditOperation();
                            }
                            catch (Exception ex)
                            {
                               LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                                Marshal.ReleaseComObject(pFeatCursor);
                                return false;
                            }
                        }
                        ===========================================================================================================*/
                    }

                    pFeature = pFeatCursor.NextFeature();
                }

                try
                {
                    pWsEdit.StopEditOperation();
                    pWsEdit.StopEditing(true);
                }
                catch
                {
                    result = false;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                result = false;
            }
            finally
            {
                if (total == 0) total = count - 1;//如果前面没有算进度条，就在这里赋值
                Marshal.ReleaseComObject(pFeatCursor);
            }

            return result;
        }

        /// <summary>
        /// 删除数据，一千条记录保存一次
        /// </summary>
        /// <param name="pFeatCls"></param>
        /// <param name="pSpatialFilter"></param>
        /// <param name="total">返回要删除的总数</param>
        /// <returns>如果删除过程中没有任何异常，则返回true；否则返回false</returns>
        private bool DeleteFeauresRapidness(IFeatureClass pFeatCls, ISpatialFilter pSpatialFilter,out int total)
        {
            bool result = true;
            total = 0;

            IWorkspaceEdit pWsEdit = (pFeatCls as IDataset).Workspace as IWorkspaceEdit;
            if (!pWsEdit.IsBeingEdited())
            {
                try
                {
                    pWsEdit.StartEditing(false);
                    pWsEdit.StartEditOperation();
                }
                catch (Exception ex)
                {
                   LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                    return false;
                }
            }

            int count = 1;
            int max = 0;

            if (progress)
            {
                LogHelper.WriteLog("正在计算包含在挖除范围内要素的总数，请耐心等待...");
                try
                {
                    max = pFeatCls.FeatureCount(pSpatialFilter);
                    total = max;
                    if (max == 0) return true;
                }
                catch(Exception ex)
                {
                    LogHelper.WriteLog("数量过大，计算总数失败，只能以假进度条显示操作过程！"+ex.Message);
                }
            }

            setSubProcessBarMax(max);

            IFeatureCursor pFeatCursor = null;

            try
            {
                pFeatCursor = pFeatCls.Search(pSpatialFilter, false);
                IFeature pFeature = null;

                pFeature = pFeatCursor.NextFeature();
                while (pFeature != null)
                {
                    if (stopAnyway) return false;

                    setSubProcessBarCurrent(count++);

                    //如果删除或保存的时候出错，则后面需要逐条遍历把该要素找出来
                    try
                    {
                        pFeature.Delete();
                        pFeature.Store();
                    }
                    catch
                    {
                        result = false;
                    }

                    if (count % 1000 == 0)
                    {
                        //如果保存失败，可能是这1000条记录中某一条出现异常，后面需要逐个遍历找出该要素
                        try
                        {
                            pWsEdit.StopEditOperation();
                            //pWsEdit.StopEditing(true);
                        }
                        catch
                        {
                            result = false;
                        }

                        //如果再次打开编辑操作失败，则直接返回false
                        try
                        {
                            pWsEdit.StartEditOperation();
                        }
                        catch (Exception ex)
                        {
                            total = 0;
                           LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                            return false;
                        }

                        ////再次打开编辑
                        //if (!pWsEdit.IsBeingEdited())
                        //{
                        //    try
                        //    {
                        //        pWsEdit.StartEditing(false);
                        //        pWsEdit.StartEditOperation();
                        //    }
                        //    catch (Exception ex)
                        //    {
                        //       LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                        //        Marshal.ReleaseComObject(pFeatCursor);
                        //        return false; ;
                        //    }
                        //}
                    }

                    pFeature = pFeatCursor.NextFeature();

                    //似乎并无此必要
                    ////如果游标遍历到了多个，此时内存会占用比较多，先把该游标释放掉，重新获取会更快一些
                    //if (pFeature != null && callbacknum > 0 && count % callbacknum == 0)
                    //{
                    //    Marshal.ReleaseComObject(pFeatCursor);
                    //    pFeatCursor = pFeatCls.Search(pSpatialFilter, false);
                    //    pFeature = pFeatCursor.NextFeature();
                    //}
                }
            }
            catch
            {
                //把能保存的先保存一下，后面遍历的可能就会少一些了
                try
                {
                    pWsEdit.StopEditOperation();
                    pWsEdit.StopEditing(true);
                }
                catch
                {
                    result = false;
                }

                Marshal.ReleaseComObject(pFeatCursor);
                return false;
            }

            try
            {
                pWsEdit.StopEditOperation();
                pWsEdit.StopEditing(true);
            }
            catch
            {
                result = false;
            }
            finally
            {
                if (total == 0) total = count - 1;//如果前面没有算进度条，就在这里赋值
                Marshal.ReleaseComObject(pFeatCursor);
            }

            return result;
        }


        /*Flush和Store的比较
         * 对同一个要素类，同一个过滤条件进行上述两种方式的删除实验如下：
         * 删除的要素个数都是290167条，IFeatureCursor.Flush()的方式花了5分23秒，用IFeature.Store()的方式
         * 花了13分18秒，很明显Flush的方式要比Store的方式快得多
         */

        /// <summary>
        /// 删除数据，逐条删除
        /// </summary>
        /// <param name="pFeatCls"></param>
        /// <param name="pSpatialFilter"></param>
        /// <param name="error">返回要删除时出错的个数</param>
        ///<param name="total">返回要删除的总数，如果快速删除的总数为0，则所有删除的总数为该变量的值</param>
        /// <returns>如果删除过程中没有任何异常，则返回true；否则返回false</returns>
        private bool DeleteFeauresOneByOne(IFeatureClass pFeatCls, ISpatialFilter pSpatialFilter,out int error,out int total)
        {
            bool result = true;
            error = 0;
            total = 0;

            IWorkspaceEdit pWsEdit = (pFeatCls as IDataset).Workspace as IWorkspaceEdit;
            if (!pWsEdit.IsBeingEdited())
            {
                try
                {
                    pWsEdit.StartEditing(false);
                }
                catch (Exception ex)
                {
                   LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                    error = -1;
                    return false;
                }
            }

            int count = 1;
            int max = 0;

            if (progress)
            {
                LogHelper.WriteLog("正在计算包含在挖除范围内要素的总数，请耐心等待...");
                try
                {
                    max = pFeatCls.FeatureCount(pSpatialFilter);
                    total = max;
                    if (max == 0) return true;
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog("数量过大，计算总数失败，只能以假进度条显示操作过程！"+ex.Message);
                }
            }

            setSubProcessBarMax(max);

            IFeatureCursor pFeatCursor = null;
            
            try
            {
                pFeatCursor = pFeatCls.Search(pSpatialFilter, false);
                IFeature pFeature = null;

                pFeature = pFeatCursor.NextFeature();

                while (pFeature  != null)
                {
                    if (stopAnyway) return false;

                    setSubProcessBarCurrent(count++);

                    try
                    {
                        pWsEdit.StartEditOperation();

                        pFeature.Delete();
                        pFeature.Store();

                        pWsEdit.StopEditOperation();
                    }
                    catch (Exception ex)
                    {
                        error++;
                       LogHelper.WriteErrLog("删除ID为[" + pFeature.OID + "]的要素出错：" + ex.Message);
                    }

                    //其实按照推理，前面执行了pWsEdit.StopEditOperation()已经对编辑做过保存，这里都不需要将编辑关闭再打开
                    //if (count % 1000 == 0)
                    //{
                    //    pWsEdit.StopEditing(true);

                    //    //再次打开编辑
                    //    if (!pWsEdit.IsBeingEdited())
                    //    {
                    //        try
                    //        {
                    //            pWsEdit.StartEditing(false);
                    //        }
                    //        catch (Exception ex)
                    //        {
                    //           LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                    //            Marshal.ReleaseComObject(pFeatCursor);
                    //            return false;
                    //        }
                    //    }
                    //}

                    pFeature = pFeatCursor.NextFeature();
                }
            }
            catch (Exception ex)
            {
                error = -1;
               LogHelper.WriteErrLog("删除出错：" + ex.Message);
                Marshal.ReleaseComObject(pFeatCursor);
                return false;
            }

            try
            {
                if (total == 0) total = count - 1;
                pWsEdit.StopEditing(true);
            }
            catch (Exception ex)
            {
                result = false;
               LogHelper.WriteErrLog("保存出错：" + ex.Message);
            }

            Marshal.ReleaseComObject(pFeatCursor);

            return result;
        }

        #endregion

        #region 与挖除范围边界相交的要素，需要进行切割
        /// <summary>
        /// 挖除数据，一千条记录保存一次
        /// </summary>
        /// <param name="pFeatCls"></param>
        /// <param name="pSpatialFilter"></param>
        /// <param name="pGeometry"></param>
        /// <param name="total">返回挖除的总数</param>
        /// <returns>如果挖除过程中没有任何异常，则返回true；否则返回false</returns>
        private bool ExcavateFeaturesRapidness(IFeatureClass pFeatCls, ISpatialFilter pSpatialFilter, IGeometry pGeometry,out int total)
        {
            bool result = true;
            total = 0;

            IWorkspaceEdit pWsEdit = (pFeatCls as IDataset).Workspace as IWorkspaceEdit;
            if (!pWsEdit.IsBeingEdited())
            {
                try
                {
                    pWsEdit.StartEditing(false);
                    pWsEdit.StartEditOperation();
                }
                catch (Exception ex)
                {
                   LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                    return false;
                }
            }

            int count = 1;
            int max = 0;

            if (progress)
            {
                LogHelper.WriteLog("正在计算与挖除范围相交要素的总数，请耐心等待...");
                try
                {
                    max = pFeatCls.FeatureCount(pSpatialFilter);
                    total = max;
                    if (max == 0) return true;
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog("数量过大，计算总数失败，只能以假进度条显示操作过程！"+ex.Message);
                }
            }

            setSubProcessBarMax(max);
            IFeatureCursor pFeatCursor = null;

            try
            {
                pFeatCursor = pFeatCls.Search(pSpatialFilter, false);
                IFeature pFeature = null;
                pFeature = pFeatCursor.NextFeature();

                while (pFeature!= null)
                {
                    if (stopAnyway) return false;

                    setSubProcessBarCurrent(count++);

                    try
                    {
                        ITopologicalOperator2 pTop = pFeature.ShapeCopy as ITopologicalOperator2;
                        pTop.IsKnownSimple_2 = false;
                        pTop.Simplify();

                        IGeometry pGeomResult = pTop.Difference(pGeometry);
                        if (pGeomResult == null || pGeomResult.IsEmpty)
                        {
                            pFeature.Delete();
                        }
                        else
                        {
                            pTop = pGeomResult as ITopologicalOperator2;
                            pTop.IsKnownSimple_2 = false;
                            pTop.Simplify();
                            pFeature.Shape = pGeomResult;
                        }

                        pFeature.Store();
                    }
                    catch
                    {
                        result = false;
                    }

                    if (count % 1000 == 0)
                    {
                        //如果保存失败，可能是这1000条记录中某一条出现异常，后面需要逐个遍历找出该要素
                        try
                        {
                            pWsEdit.StopEditOperation();
                            //pWsEdit.StopEditing(true);
                        }
                        catch
                        {
                            result = false;
                        }

                        //如果再次打开编辑操作失败，则直接返回false，并且操作的总数也不能按照该函数算了
                        try
                        {
                            pWsEdit.StartEditOperation();
                        }
                        catch (Exception ex)
                        {
                            total = 0;
                           LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                            return false;
                        }

                        ////再次打开编辑
                        //if (!pWsEdit.IsBeingEdited())
                        //{
                        //    try
                        //    {
                        //        pWsEdit.StartEditing(false);
                        //        pWsEdit.StartEditOperation();
                        //    }
                        //    catch (Exception ex)
                        //    {
                        //       LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                        //        Marshal.ReleaseComObject(pFeatCursor);
                        //        return false; ;
                        //    }
                        //}
                    }

                    pFeature = pFeatCursor.NextFeature();

                    ////如果游标遍历到了多个，此时内存会占用比较多，先把该游标释放掉，重新获取会更快一些
                    //if (pFeature != null && callbacknum > 0 && count % callbacknum == 0)
                    //{
                    //    Marshal.ReleaseComObject(pFeatCursor);
                    //    pFeatCursor = pFeatCls.Search(pSpatialFilter, false);
                    //    pFeature = pFeatCursor.NextFeature();
                    //}
                }
            }
            catch
            {
                //其实想想，也没必要
                ////把能保存的先保存一下，后面遍历的可能就会少一些了
                //try
                //{
                //    pWsEdit.StopEditOperation();
                //    pWsEdit.StopEditing(true);
                //}
                //catch
                //{
                //    result = false;
                //}

                total = 0;
                Marshal.ReleaseComObject(pFeatCursor);
                return false;
            }
            try
            {
                if (total == 0) total = count - 1;
                pWsEdit.StopEditOperation();
                pWsEdit.StopEditing(true);
            }
            catch
            {
                result = false;
            }

            Marshal.ReleaseComObject(pFeatCursor);
            return result;
        }

        /// <summary>
        /// 挖除数据，一千条记录保存一次，用Flush的方式速度更快
        /// </summary>
        /// <param name="pFeatCls"></param>
        /// <param name="pSpatialFilter"></param>
        /// <param name="pGeometry"></param>
        /// <param name="total">返回挖除的总数</param>
        /// <returns>如果挖除过程中没有任何异常，则返回true；否则返回false</returns>
        private bool ExcavateFeaturesRapidnessFlush(IFeatureClass pFeatCls, ISpatialFilter pSpatialFilter, IGeometry pGeometry, out int total)
        {
            bool result = true;
            total = 0;

            IWorkspaceEdit pWsEdit = (pFeatCls as IDataset).Workspace as IWorkspaceEdit;
            if (!pWsEdit.IsBeingEdited())
            {
                try
                {
                    pWsEdit.StartEditing(false);
                    pWsEdit.StartEditOperation();
                }
                catch (Exception ex)
                {
                   LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                    return false;
                }
            }

            int count = 1;
            int max = 0;

            if (progress)
            {
                LogHelper.WriteLog("正在计算与挖除范围相交要素的总数，请耐心等待...");
                try
                {
                    max = pFeatCls.FeatureCount(pSpatialFilter);
                    total = max;
                    if (max == 0) return true;
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog("数量过大，计算总数失败，只能以假进度条显示操作过程！"+ex.Message);
                }
            }

            setSubProcessBarMax(max);
            IFeatureCursor pFeatCursor = null;

            try
            {
                pFeatCursor = pFeatCls.Update(pSpatialFilter, false);
                IFeature pFeature = null;
                pFeature = pFeatCursor.NextFeature();

                while (pFeature != null)
                {
                    if (stopAnyway) return false;

                    setSubProcessBarCurrent(count++);

                    try
                    {
                        ITopologicalOperator2 pTop = pFeature.ShapeCopy as ITopologicalOperator2;
                        pTop.IsKnownSimple_2 = false;
                        pTop.Simplify();

                        IGeometry pGeomResult = pTop.Difference(pGeometry);
                        if (pGeomResult == null || pGeomResult.IsEmpty)
                        {
                            pFeature.Delete();
                        }
                        else
                        {
                            pTop = pGeomResult as ITopologicalOperator2;
                            pTop.IsKnownSimple_2 = false;
                            pTop.Simplify();
                            pFeature.Shape = pGeomResult;
                        }

                        pFeature.Store();
                    }
                    catch
                    {
                        result = false;
                    }

                    if (count % 1000 == 0)
                    {
                        //如果保存失败，可能是这1000条记录中某一条出现异常，后面需要逐个遍历找出该要素
                        try
                        {
                            pFeatCursor.Flush();
                            pWsEdit.StopEditOperation();
                            //pWsEdit.StopEditing(true);
                        }
                        catch
                        {
                            result = false;
                        }

                        //如果再次打开编辑操作失败，则直接返回false，并且操作的总数也不能按照该函数算了
                        try
                        {
                            pWsEdit.StartEditOperation();
                        }
                        catch (Exception ex)
                        {
                            total = 0;
                           LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                            return false;
                        }
                    }

                    pFeature = pFeatCursor.NextFeature();

                }
            }
            catch
            {
                total = 0;
                Marshal.ReleaseComObject(pFeatCursor);
                return false;
            }
            try
            {
                if (total == 0) total = count - 1;
                pWsEdit.StopEditOperation();
                pWsEdit.StopEditing(true);
            }
            catch
            {
                result = false;
            }

            Marshal.ReleaseComObject(pFeatCursor);
            return result;
        }

        /// <summary>
        /// 挖除数据，逐条挖除
        /// </summary>
        /// <param name="pFeatCls"></param>
        /// <param name="pSpatialFilter"></param>
        /// <param name="pGeometry"></param>
        /// <param name="error">返回要挖除时出错的个数</param>
        ///<param name="total">返回要挖除的总数，如果快速挖除的总数为0，则所有挖除的总数为该变量的值</param>
        /// <returns></returns>
        private bool ExcavateFeaturesOneByOne(IFeatureClass pFeatCls, ISpatialFilter pSpatialFilter, IGeometry pGeometry,out int error,out int total)
        {
            bool result = true;
            error = 0;
            total = 0;

            IWorkspaceEdit pWsEdit = (pFeatCls as IDataset).Workspace as IWorkspaceEdit;
            if (!pWsEdit.IsBeingEdited())
            {
                try
                {
                    pWsEdit.StartEditing(false);
                }
                catch (Exception ex)
                {
                    error = -1;
                   LogHelper.WriteErrLog("打开数据[" + pFeatCls.AliasName + "]所在工作空间的编辑失败：" + ex.Message + "\n");
                    return false;
                }
            }

            int count = 1;
            int max = 0;

            if (progress)
            {
                LogHelper.WriteLog("正在计算与挖除范围相交要素的总数，请耐心等待...");
                try
                {
                    max = pFeatCls.FeatureCount(pSpatialFilter);
                    total = max;
                    if (max == 0) return true;
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog("数量过大，计算总数失败，只能以假进度条显示操作过程！"+ex.Message);
                }
            }

            setSubProcessBarMax(max);

            IFeatureCursor pFeatCursor = null;

            try
            {
                pFeatCursor = pFeatCls.Search(pSpatialFilter, false);
                IFeature pFeature = null;

                pFeature = pFeatCursor.NextFeature();

                while (pFeature!= null)
                {
                    if (stopAnyway) return false;

                    setSubProcessBarCurrent(count++);

                    try
                    {
                        pWsEdit.StartEditOperation();

                        ITopologicalOperator2 pTop = pFeature.ShapeCopy as ITopologicalOperator2;
                        pTop.IsKnownSimple_2 = false;
                        pTop.Simplify();

                        IGeometry pGeomResult = pTop.Difference(pGeometry);
                        if (pGeomResult == null || pGeomResult.IsEmpty)
                        {
                            pFeature.Delete();
                        }
                        else
                        {
                            pTop = pGeomResult as ITopologicalOperator2;
                            pTop.IsKnownSimple_2 = false;
                            pTop.Simplify();
                            pFeature.Shape = pGeomResult;
                        }

                        pFeature.Store();
                        pWsEdit.StopEditOperation();
                    }
                    catch (Exception ex)
                    {
                        error++;
                        result = false;
                       LogHelper.WriteErrLog("挖除ID为[" + pFeature.OID + "]的要素出错：" + ex.Message);
                    }

                    pFeature = pFeatCursor.NextFeature();

                }
            }
            catch (Exception ex)
            {
                error = -1;
               LogHelper.WriteErrLog("挖除出错：" + ex.Message);
                return false;
            }

            try
            {
                pWsEdit.StopEditing(true);
            }
            catch (Exception ex)
            {
                result = false;
               LogHelper.WriteErrLog("保存出错：" + ex.Message);
            }

            if (total == 0) total = count - 1;
            Marshal.ReleaseComObject(pFeatCursor);

            return result;
        }

        #endregion
    }
}
